/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package controller;

import static java.lang.System.out;


import cart.ShoppingCart;
import cart.ShoppingCartItem;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import entity.Category;
import entity.Customer;
import entity.CustomerOrder;
import entity.CustomerOrderHasProduct;
import entity.Genre;
import entity.Product;
import entity.Serie;
import entity.SerieHasGenre;
import form.CustomerForm;
import form.VisaForm;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.persistence.EntityTransaction;
import javax.servlet.http.HttpSession;

import session.CategoryFacade;
import session.CustomerFacade;
import session.CustomerOrderFacade;
import session.CustomerOrderHasProductFacade;
import session.GenreFacade;
import session.ProductFacade;
import session.SerieFacade;
import session.SerieHasGenreFacade;

/**
 *
 * @author tgiunipero
 */
@WebServlet(name = "Controller",
            loadOnStartup = 1,
            urlPatterns = {"/index",
                           "/category",
                           "/serie",
                           "/signup",
                           "/account",
                           "/cart",
                           "/checkout",
                           "/purchase",
                           "/ordersummary",
                           "/chooseLanguage"})
public class ControllerServlet extends HttpServlet
{    
    private HttpSession session;
    @EJB
    private CategoryFacade categoryFacade;
    @EJB
    private CustomerFacade customerFacade;
    @EJB
    private CustomerOrderFacade customerOrderFacade;
    @EJB
    private CustomerOrderHasProductFacade customerOrderHasProductFacade;
    @EJB
    private GenreFacade genreFacade;
    @EJB
    private ProductFacade productFacade;
    @EJB
    private SerieFacade serieFacade;
    @EJB
    private SerieHasGenreFacade serieHasGenreFacade;
    
    
    @Override
    public void init() throws ServletException
    {
        getServletContext().setAttribute("categories", categoryFacade.findAll());
    }

    /**
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        session = request.getSession();
        
        String userPath;
        
        if (request.getServletPath().equals(""))
        {
            userPath = "/index";
        }
        else
        {            
            userPath = request.getServletPath();
        }
        
        request.setAttribute("userPath", userPath);
                
        /****************** Index page ************************ 
        *******************************************************/
        if (userPath.equals("/index"))
        {
            List<Product> lastProduct = productFacade.findOrderByLast();
            request.setAttribute("lastProduct", lastProduct);
            
            List<Serie> lastSerieFromProduct = new ArrayList<>();
            for(Product p : lastProduct)
            {
                Serie s = serieFacade.find(p.getSerieId());
                lastSerieFromProduct.add(s);
            }
            request.setAttribute("lastSerieFromProduct", lastSerieFromProduct);
            
            
            List<Integer> customerOrderHasProductByCount = customerOrderHasProductFacade.findProductByCount();
            request.setAttribute("customerOrderHasProductByCount", customerOrderHasProductByCount);            
            
            List<Product> productByCount = new ArrayList<>();
            List<Serie> serieProductByCount = new ArrayList<>();
            for(Integer i : customerOrderHasProductByCount) {
                Product p = productFacade.find(i);
                Serie s = serieFacade.find(p.getSerieId());
                productByCount.add(p);
                serieProductByCount.add(s);
            }
            request.setAttribute("productByCount", productByCount);
            request.setAttribute("serieProductByCount", serieProductByCount);                  
        }
        /****************** Category page ********************** 
        *******************************************************/
        else if (userPath.equals("/category"))
        {     
            String categoryId = request.getParameter("id");
        
            if(categoryId != null)
            {
                Category selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
                request.setAttribute("selectedCategory", selectedCategory);
                
                List<Serie> categorySeries = serieFacade.findByCategoryId(Short.parseShort(categoryId));
                request.setAttribute("categorySeries", categorySeries);
                
                List<String> imageSeries = new ArrayList<>();
                for(Serie s : categorySeries) {
                    imageSeries.add(productFacade.findLastImage(s.getId()));
                }
                request.setAttribute("imageSeries", imageSeries);  
            }
        }       
        /****************** Serie page ************************ 
        *******************************************************/
        else if(userPath.equals("/serie"))
        {                         
            String serieId = request.getParameter("id");
            Category serieCategory;

            Serie selectedSerie;
            List<Product> serieProducts;
            List<String> genres = new ArrayList<String>();
            if(serieId != null)
            {         
                //get selected category
                selectedSerie = serieFacade.find(Integer.parseInt(serieId));
                serieProducts = productFacade.findBySerieId(Short.parseShort(serieId));
                serieCategory = categoryFacade.find(Short.parseShort(String.valueOf(selectedSerie.getCategoryId())));

                List<SerieHasGenre> serieHasGenreList = serieHasGenreFacade.findBySerieId(Integer.parseInt(serieId));
                for(SerieHasGenre serieHasGenre : serieHasGenreList) {
                    genres.add(genreFacade.find(serieHasGenre.getSerieHasGenrePK().getGenreId()).getName());
                }

                //place selected category in request page
                request.setAttribute("selectedSerie", selectedSerie);
                request.setAttribute("serieProducts", serieProducts);
                request.setAttribute("genres", genres);
                request.setAttribute("serieCategory", serieCategory);               
            }
        }        
        /****************** Sign up page ***********************
        *******************************************************/
        else if (userPath.equals("/signup"))
        {           
            if(session.getAttribute("user") != null)
            {
                response.sendRedirect("index");
            }
        }        
        /****************** Account page ***********************
        *******************************************************/
        else if (userPath.equals("/account"))
        {
            Customer user = (Customer)session.getAttribute("user");
            
            List<CustomerOrder> listCustomerOrder = customerOrderFacade.findByCustomerId(user.getId());

            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
            
            List<String> listOrderDate = new ArrayList<>();
            
            for(CustomerOrder co : listCustomerOrder)
            {
                listOrderDate.add(sdf.format(co.getDateCreated()));
            }

            request.setAttribute("listCustomerOrder", listCustomerOrder);
            request.setAttribute("listOrderDate", listOrderDate);
        }
        /****************** Cart page ************************* 
        *******************************************************/
        else if (userPath.equals("/cart"))
        {
            ShoppingCart cart = (ShoppingCart) session.getAttribute("cart");
            String clear = request.getParameter("clear");
            
            if ((clear != null) && clear.equals("true"))
            {
                cart.clear();
            }
            
            if(cart != null)
            {
                cart.calculateTotal("0");
            }
            
            userPath = "/cart";
        }
        /****************** Checkout page ********************* 
        *******************************************************/
        else if (userPath.equals("/checkout"))
        {
            if(session.getAttribute("user") == null)
            {
                userPath = "/checkoutFilter";
            }
            else {
                userPath = "/checkout";
            }
        }        
        /**************** Order summary page ****************** 
        *******************************************************/
        else if (userPath.equals("/ordersummary"))
        {
            String idOrder = request.getParameter("idOrder");
            String orderValidated = request.getParameter("orderValidated");
            
            CustomerOrder customerOrder = customerOrderFacade.find(Integer.parseInt(idOrder));
            Customer user = (Customer)session.getAttribute("user");
            
            if(customerOrder.getCustomerId() == user.getId())
            {
                List<CustomerOrderHasProduct> listCustomerOrderHasProduct = customerOrderHasProductFacade.findByCustomerOrderId(Integer.parseInt(idOrder));

                List<Product> listProduct = new ArrayList<>();
                List<Serie> listSerie = new ArrayList<>();

                for(CustomerOrderHasProduct cohp : listCustomerOrderHasProduct)
                {
                    Product product = productFacade.find(cohp.getCustomerOrderHasProductPK().getProductId());
                    listProduct.add(product);

                    Serie serie = serieFacade.find(product.getSerieId());
                    listSerie.add(serie);
                }

                SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

                Date orderDate = customerOrder.getDateCreated();
                long time = orderDate.getTime();
                Date deliveryDate = (Date)orderDate.clone();
                deliveryDate.setTime(time + customerOrder.getDeliveryTime()* 24 * 60 *60 * 1000);
                BigDecimal productsCost = customerOrder.getAmount().subtract(customerOrder.getDeliveryCost());

                request.setAttribute("orderValidated", orderValidated);
                request.setAttribute("customerOrder", customerOrder);
                request.setAttribute("orderDate", sdf.format(orderDate));
                request.setAttribute("deliveryDate", sdf.format(deliveryDate));
                request.setAttribute("productsCost", productsCost);
                request.setAttribute("listCustomerOrderHasProduct", listCustomerOrderHasProduct);
                request.setAttribute("listProduct", listProduct);
                request.setAttribute("listSerie", listSerie);
            }
            else
            {
                response.sendRedirect("index");
            }
        }
        /**************** Choose language page ****************** 
        *******************************************************/
        else if (userPath.equals("/chooseLanguage"))
        {
        } 

        // use RequestDispatcher to forward request internally
        String url = "/WEB-INF/view" + userPath + ".jsp";

        try {
            request.getRequestDispatcher(url).forward(request, response);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        session = request.getSession();
        
        String userPath = request.getServletPath();        
        
        /******************** Sign in widget ****************** 
        *******************************************************/
        if(request.getParameter("signin") != null)
        {
            String emaillog = request.getParameter("emaillog");
            String passwordlog = request.getParameter("passwordlog");
            
            try
            {
                Customer user = customerFacade.findForConnection(emaillog, passwordlog);
                session.setAttribute("user", user);
            }
            catch(Exception e)
            {
                request.setAttribute("logerror", "Email and password don't match.");
            }
            
            this.doGet(request, response);
        }
        
        
        /****************** Sign out widget ******************* 
        *******************************************************/
        else if(request.getParameter("signout") != null)
        {
            session.removeAttribute("user");
            
            if(userPath.equals("/account") || userPath.equals("/purchase") || userPath.equals("/ordersummary"))
            {
                response.sendRedirect("index");
            }
            else
            {
                this.doGet(request, response);       
            }
        }        
        else
        {
            ShoppingCart cart = (ShoppingCart) session.getAttribute("cart");

            /******************* Register Form ******************** 
            *******************************************************/
            if(userPath.equals("/signup"))
            {
                try
                {
                    HashMap<String, String> errors = CustomerForm.validateForm(request, customerFacade);
                    if(errors.isEmpty())
                    {
                        customerFacade.insertCustomer(request);
                        Customer user = customerFacade.findByEmail(request.getParameter("email"));
                        session.setAttribute("user", user);
                        
                        response.sendRedirect("index");
                    }
                    else
                    {
                        request.setAttribute("errors", errors);
                        throw new Exception();
                    }
                }
                catch(Exception e)
                {
                    request.setAttribute("fname", request.getParameter("fname"));
                    request.setAttribute("lname", request.getParameter("lname"));
                    request.setAttribute("email", request.getParameter("email"));
                    request.setAttribute("phone", request.getParameter("phone"));
                    request.setAttribute("address", request.getParameter("address"));
                    this.getServletContext().getRequestDispatcher("/WEB-INF/view" + userPath + ".jsp").forward(request, response);
                }
            }
            /****************** Account page ***********************
            *******************************************************/
            else if (userPath.equals("/account"))
            {
                try
                {
                    Customer user = (Customer)session.getAttribute("user");
                    HashMap<String, String> errors = CustomerForm.updateForm(request, customerFacade);
                    if(errors.isEmpty())
                    {
                        customerFacade.updateCustomer(request, user);
                        user.setPhone(request.getParameter("phone"));
                        user.setAddress(request.getParameter("address"));
                        response.sendRedirect("account");
                    }
                    else
                    {
                        request.setAttribute("errors", errors);
                        throw new Exception();
                    }
                }
                catch(Exception e)
                {
                    request.setAttribute("phone", request.getParameter("phone"));
                    request.setAttribute("address", request.getParameter("address"));
                    this.doGet(request, response);
                }
            }
            /******************* Add to cart action ******************* 
            *******************************************************/
            else if (userPath.equals("/serie"))
            {
                // if user is adding item to cart for first time
                // create cart object and attach it to user session
                if (cart == null)
                {
                    cart = new ShoppingCart();
                    session.setAttribute("cart", cart);
                }
                // get user input from request
                String productId = request.getParameter("idProduct");
                String serieId = request.getParameter("id");

                if (!productId.isEmpty())
                {
                    Product product = productFacade.find(Integer.parseInt(productId));
                    Serie serie = serieFacade.find(Integer.parseInt(serieId));
                    cart.addItem(product, serie);
                    cart.calculateTotal("0");
                }
                response.sendRedirect("serie?id=" + serieId);
            }                
            /***************** Update cart action ****************** 
            *******************************************************/
            else if (userPath.equals("/cart"))
            {
                // get input from request
                String productId = request.getParameter("productId");
                String quantity = request.getParameter("quantity");

                Product product = productFacade.find(Integer.parseInt(productId));
                cart.update(product, quantity);
                cart.calculateTotal("0");
                
                response.sendRedirect("cart");
            }
           /****************** Purchase action ******************* 
            *******************************************************/
            else if (userPath.equals("/checkout"))
            {        
                if(request.getParameter("checkoutRegister") != null) {
                    out.print("checkoutreg"); 
                    
                    try
                    {
                        HashMap<String, String> errors = CustomerForm.validateForm(request, customerFacade);
                        if(errors.isEmpty())
                        {
                            customerFacade.insertCustomer(request);
                            Customer user = customerFacade.findByEmail(request.getParameter("email"));
                            session.setAttribute("user", user);
                        }
                        else
                        {
                            request.setAttribute("errors", errors);
                            throw new Exception();
                        }
                    }
                    catch(Exception e)
                    {
                        request.setAttribute("fname", request.getParameter("fname"));
                        request.setAttribute("lname", request.getParameter("lname"));
                        request.setAttribute("email", request.getParameter("email"));
                        request.setAttribute("phone", request.getParameter("phone"));
                        request.setAttribute("address", request.getParameter("address"));
                        userPath = "/checkoutFilter";
                        this.getServletContext().getRequestDispatcher("/WEB-INF/view" + userPath + ".jsp").forward(request, response);
                    }
                }
                else if(request.getParameter("checkoutSignin") != null) {
                    out.print("checkoutsignin"); 
                    String email_s = request.getParameter("email_s");
                    String password_s = request.getParameter("password_s");

                    try
                    {
                        Customer user = customerFacade.findForConnection(email_s, password_s);
                        session.setAttribute("user", user);
                    }
                    catch(Exception e)
                    {
                        request.setAttribute("s_error", "Email and password don't match.");
                    }

                    this.doGet(request, response);
                }
                else if(request.getParameter("checkoutPurchase") != null){
                    
                    if (cart == null)
                    {
                        response.sendRedirect("index");
                    }
                    else
                    {
                        try
                        {
                            List<String> errors = VisaForm.validateForm(request);               

                            if(errors.isEmpty())
                            {
                                Customer customer = (Customer)session.getAttribute("user");

                                try
                                {
                                    customerOrderFacade.insertCustomerOrder(request, cart, customer.getId());
                                    CustomerOrder customerOrder =  customerOrderFacade.findByLastCustomerId(customer.getId());
                                    
                                    List<ShoppingCartItem> listSCI = cart.getItems();

                                    for(ShoppingCartItem sci : listSCI)
                                    {
                                        customerOrderHasProductFacade.insertCustomerOrderHasProduct(customerOrder.getId(), sci.getProduct().getId(), sci.getQuantity());
                                    }
                                    
                                    session.removeAttribute("cart");
                                    cart = null;
                                    
                                    response.sendRedirect("ordersummary?idOrder=" + customerOrder.getId().toString() + "&orderValidated=true");
                                }
                                catch (Exception e)
                                {
                                    request.setAttribute("fname", request.getParameter("fname"));
                                    request.setAttribute("lname", request.getParameter("lname"));
                                    request.setAttribute("email", request.getParameter("email"));
                                    request.setAttribute("phone", request.getParameter("phone"));
                                    request.setAttribute("adress", request.getParameter("adress"));
                                    request.setAttribute("card_type", request.getParameter("card_type"));
                                    request.setAttribute("card_number", request.getParameter("card_number"));
                                    request.setAttribute("card_expiration", request.getParameter("card_expiration"));
                                    request.setAttribute("card_crypt", request.getParameter("card_crypt"));
                                    request.setAttribute("delivery", request.getParameter("delivery"));
                                }                          
                            }                        
                            else
                            {
                                request.setAttribute("errors", errors);
                                throw new Exception();
                            }
                        }
                        catch(Exception e)
                        {
                            request.setAttribute("fname", request.getParameter("fname"));
                            request.setAttribute("lname", request.getParameter("lname"));
                            request.setAttribute("email", request.getParameter("email"));
                            request.setAttribute("phone", request.getParameter("phone"));
                            request.setAttribute("adress", request.getParameter("adress"));
                            request.setAttribute("card_type", request.getParameter("card_type"));
                            request.setAttribute("card_number", request.getParameter("card_number"));
                            request.setAttribute("card_expiration", request.getParameter("card_expiration"));
                            request.setAttribute("card_crypt", request.getParameter("card_crypt"));
                            request.setAttribute("delivery", request.getParameter("delivery"));
                        }
                    }
                }           
            }

            // use RequestDispatcher to forward request internally
            String url = "/WEB-INF/view" + userPath + ".jsp";

            try {
                request.getRequestDispatcher(url).forward(request, response);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}
